package cn.iborder.utils;

import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;

import javax.websocket.Session;

import com.jcraft.jsch.Channel;
import com.jcraft.jsch.ChannelShell;
import com.jcraft.jsch.JSch;
import com.jcraft.jsch.JSchException;
import com.jfinal.log.Log;

import cn.iborder.entity.Machine;

public class SshClient {
	private static Log log = TrcLog.getLogFile();
	private com.jcraft.jsch.Session sess;
	private ChannelShell channel;
	private InputStream in;
	private OutputStream out;
	private BufferedWriter inToShell;

	public void connect(Machine machine) {
		log.info("[SshClient]connect");
		try {
			JSch jsch = new JSch();
			sess = jsch.getSession(machine.getUsername(), machine.getHostname(), machine.getPort());
			if (sess == null) {
				throw new JSchException("Attempt get session fail");
			}
			sess.setConfig("PreferredAuthentications", "password");
			// 设置第一次登陆的时候提示，可选值：(ask | yes | no)
			sess.setConfig("StrictHostKeyChecking", "no");
			// 设置登陆主机的密码
			sess.setPassword(machine.getPassword());// 设置密码
			//设置发送保持存活消息间隔时间
			sess.setServerAliveInterval(1000*60);
			//设置发送保持存活消息服务器响应超时时间
			sess.setServerAliveCountMax(1000*60);
			//设置为守护进程
			sess.setDaemonThread(true);

			// 设置登陆超时时间
			sess.connect(30000);
			if (sess.isConnected()) {
				log.info("[SshClient.connect]verify: pass");
			} else {
				log.info("[SshClient.connect]verify: fail");
				throw new JSchException("ssh verify: fail");
			}

			channel = (ChannelShell) sess.openChannel("shell");

			in = channel.getInputStream();
			out = channel.getOutputStream();
			channel.setPty(true);
			channel.setPtyType("xterm");
			channel.setPtySize(90, 30, 0, 0);
			channel.connect();
			channel.start();

			inToShell = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
		} catch (JSchException e) {
			throw new RuntimeException(e);
		} catch (UnsupportedEncodingException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		} catch (IOException e) {
			// TODO Auto-generated catch block
			throw new RuntimeException(e);
		}
	}
	
	/**
	 * 重新打开通道
	 * @throws IOException
	 * @throws JSchException
	 */
	public void openChannel() throws IOException, JSchException{
		if (getSessStatus()) {
			if (getChannelStatus()) {
				log.info("[SshClient.openChannel]open Channel again");
				in = channel.getInputStream();
				out = channel.getOutputStream();
				channel.setPty(true);
				channel.setPtyType("xterm");
				channel.setPtySize(90, 30, 0, 0);
				channel.connect();
				channel.start();

				inToShell = new BufferedWriter(new OutputStreamWriter(out, "UTF-8"));
			}
		}
	}

	/**
	 * 输入shell命令到服务器
	 * 
	 * @param text
	 * @throws IOException
	 */
	public void write(String cmd) throws IOException {
		if (inToShell != null) {
			inToShell.write(cmd);
			inToShell.flush();
		}
	}

	/**
	 * 设置pty窗口大小
	 * 
	 * @param term_width_characters
	 * @param term_height_characters
	 * @throws IOException
	 */
	public void setPtySize(int term_width_characters, int term_height_characters) throws IOException {
		channel.setPtySize(term_width_characters, term_height_characters, 0, 0);
	}

	/**
	 * 接收输出shell响应
	 * 
	 * @param session
	 */
	public void getShellOutput(Session wsSession) {
		new ShellOutput(wsSession, in).start();
	}

	public void disconnect() {
		if (channel != null) {
			channel.disconnect();
		}
		if (sess != null) {
			sess.disconnect();
		}
	}

	/**
	 * 返回session连接状态
	 * @return
	 */
	public boolean getSessStatus() {
		return sess.isConnected();
	}

	/**
	 * 返回Channel通道开闭状态
	 * @return
	 */
	public boolean getChannelStatus() {
		return channel.isClosed();
	}

}
